#pragma once

#include <vector>

class WaveForm
{
public:
	typedef short int							SampleType;
	typedef std::vector<SampleType>				Samples;
	typedef std::vector<float>					NormalizedSamples;
	typedef std::vector<std::pair<float,float>>	FFTBins;			// sin/cos or real/imaginary pairs or 

	WaveForm();
	
	const Samples&					getSamples() const	{ return mSamples; }
	Samples&						getSamples()		{ return mSamples; }
	void							getNormalizedSamples( NormalizedSamples& normalizedSamples ) const;

	bool							writeToRaw( const char* fileName ) const		{ return writeSamplesToRaw( fileName, getSamples() ); }
	bool							writeToWave( const char* fileName ) const		{ return writeSamplesToWave( fileName, getSamples() ); }


	// Static methods
	static WaveForm*				readFromRaw( const char* fileName );
	static WaveForm*				readFromWave( const char* fileName );
	static WaveForm*				createFromSinusoid( std::size_t numSamples, float numCycles, float amplitude );

	static void						createSinusoid( std::size_t numSamples, float numCyles, float amplitude, Samples& samples );
	
	static bool						readSamplesFromRaw( const char* fileName, Samples& samples );
	static bool						writeSamplesToRaw( const char* fileName, const Samples& samples );
	
	static bool						readSamplesFromWave( const char* fileName, Samples& samples );
	static bool						writeSamplesToWave( const char* fileName, const Samples& samples );

	static void						normalizeSamples( const Samples& samples, NormalizedSamples& normalizedSamples );
	static void						unnormalizeSamples( const NormalizedSamples& normalizedSamples, Samples& samples );
	
	static void						calculateDST( const NormalizedSamples& normalizedSamples, std::vector<float>& dst );
	static void						calculateDFT( const NormalizedSamples& normalizedSamples, FFTBins& fftBins );
	static void						calculateFFT( const NormalizedSamples& normalizedSamples, FFTBins& fftBins );
	static void						calculateInverseFFT( const  FFTBins& fftBins, NormalizedSamples& normalizedSamples );

	// not quite sure what to call this
	static float					calculatePowerLevel( const FFTBins& fftBins );


	static void						doStuff( NormalizedSamples& normalizedSamples );
	
private:
	static void						smbFft(float *fftBuffer, long fftFrameSize, long sign);

	Samples							mSamples;
};

